#include "handle.h"

static const char *TAG = "HANDLE";

char whole_decode[20480];

int verify_account(char *buf)
{
    MYAPP_LOGD(TAG, "In verify_account func");
    MYAPP_LOGD(TAG, "@Echo->account:%s", buf);

    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
    memset(recvbuf, 0, sizeof(recvbuf));

    sprintf(sendbuf, "USER %s\r\n", buf);
    tcp_send_data(sendbuf, recvbuf, 0);

    return 1;
}

int verify_password(char *buf)
{
    MYAPP_LOGD(TAG, "In verify_password func");
    MYAPP_LOGD(TAG, "@Echo->password:%s", buf);

    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
    memset(recvbuf, 0, sizeof(recvbuf));

    sprintf(sendbuf, "PASS %s\r\n", buf);
    tcp_send_data(sendbuf, recvbuf, 0);
    if (strstr(recvbuf, "ERR") == NULL)
    {
        return 1;
    }
    else
    {
        printf("Wrong account or password\n");
        return 2;
    }
}

int verify_domain(char *buf)
{
    MYAPP_LOGD(TAG, "In verify_domain func");
    MYAPP_LOGD(TAG, "@Echo->domain:%s", buf);
    printf("Searching for domain:%s, Please wait!\n", buf);
    int ret = search_dns(buf);
    if (!ret)
    {

        printf("Could not resolve host! Please try again!\n");
        return 0;
    }
    else
    {
        printf("Domain name available!\n");
        printf("Trying to get connection to server!\n");
        int ret_con = get_connection();
        if (!ret_con)
        {
            printf("Could not connect to host! Please try again!\n");
        }
        else
        {
            printf("Connect success!\n");
            tcp_read_data();
            return 1;
        }
    }
}

int get_list(int mode)
{
    MYAPP_LOGD(TAG, "In get_list func");
    char recvbuf[BUFFER_SIZE];
    memset(recvbuf, 0, sizeof(recvbuf));
    tcp_send_data("LIST\r\n", recvbuf, 0);
    if (mode == 1)
    {
        printf("%s\n", recvbuf);
    }
    int temp_n = 0;
    char *test = strstr(recvbuf, " ") + 1;
    temp_n = *test - '0';
    return temp_n;
    MYAPP_LOGD(TAG, "Get list done");
}

void get_status()
{
    char recvbuf[BUFFER_SIZE];
    memset(recvbuf, 0, sizeof(recvbuf));
    tcp_send_data("STAT\r\n", recvbuf, 0);
    printf("%s", recvbuf);
    MYAPP_LOGD(TAG, "Get status done");
}

void search_text()
{
    MYAPP_LOGD(TAG, "In search_text func");
    printf("Please input the text you want to search\n");

    char *text = input_email_name();
#ifdef release
    // info level
    char *path = "./resource/";
#else
    char *path = "../resource";
#endif
    DIR *dir;
    char pathname[255];             //目录的全名，=当前目录名+子目录名
    if ((dir = opendir(path)) == 0) //无法打开则跳过
    {
        printf("open %s failed!\n", path);
    }
    struct dirent *stdir;
    FILE *fp;
    char *str;
    char txt[1000];
    char *content;
    char *ifFind;
    int filesize;
    int filenum = 0;
    int cor_filenum = 0;
    while (1)
    {
        if ((stdir = readdir(dir)) == 0)
        {
            printf("You have %d emails.", filenum);
            printf("{%d} emails has the information {%s}.\n", cor_filenum, text);
            break;
        }

        if (stdir->d_type == 8)
        {
#ifdef release
            // info level
            char *path = "./resource/";
#else
            char *path = "../resource/";
#endif

            char *final_Path = malloc(100);
            strcat(final_Path, path);
            strcat(final_Path, stdir->d_name);

            fp = fopen(final_Path, "r");

            str = (char *)malloc(500);

            str[0] = 0;

            rewind(fp);

            while ((fgets(txt, 1000, fp)) != NULL)
            {
                strcat(str, txt);
            }
            MYAPP_LOGD(TAG, "%s\n", str);
            if (strstr(str, "bit") != NULL)
            {
                content = strstr(str, "bit") + 6;
                char *str_end = strstr(content, "\n") + 1;
                char *str_end_se = strstr(str_end, "\n");
                // printf("%s\n", str_end);
                char final_content[str_end_se - str_end];
                strncpy(final_content, str_end, str_end_se - str_end);
                if (strstr(final_content, text) != NULL)
                {
                    printf("In %s find %s \n", stdir->d_name, text);
                    cor_filenum = cor_filenum + 1;
                }
                // fclose(fp);
                filenum = filenum + 1;
            }
            else
            {
                content = strstr(str, ".\r");
                if (strstr(content, text) != NULL)
                {
                    printf("In %s find %s \n", stdir->d_name, text);
                    cor_filenum = cor_filenum + 1;
                }
                // fclose(fp);
                filenum = filenum + 1;
            }

            // printf("%s\n", final_content);
            MYAPP_LOGD(TAG, "%s\n", content);
        }
    }
}
char *display_subjects()
{
    MYAPP_LOGD(TAG, "In display_subjects func");
    int num = 0;
    char *result;
    char *fin_result;
    char *temp_result_fi;
    char temp_result_se[20480];

    char temp_result_th;
    do
    {
        printf("Please input the mail number\n");
        num = input_email_num();
        char sendbuf[BUFFER_SIZE];
        char recvbuf[BUFFER_SIZE];
        memset(recvbuf, 0, sizeof(recvbuf));
        if (checkinput_num(num) == 1)
        {
            sprintf(sendbuf, "RETR %d\r\n", num);
            tcp_send_data(sendbuf, recvbuf, 3);
            result = search_decode_whole(recvbuf, result);
            if (strstr(result, "<div") != NULL)
            {
                temp_result_fi = strstr(result, "<div");
                char final_content[20480];
                strncpy(final_content, result, temp_result_fi - result);

                strcpy(temp_result_se, temp_result_fi);
                temp_result_th = temp_result_se[0];

                int mode = 0;
                for (int i, j = 0; i < 1000; i++, j++)
                {
                    if (temp_result_th == '<')
                    {
                        mode = 1;
                    }
                    if (temp_result_th == '>')
                    {
                        mode = 2;
                    }
                    temp_result_th = temp_result_se[i];
                    if (temp_result_th == '<')
                    {
                        temp_result_se[i] = ' ';
                    }
                    if (mode == 1)
                    {
                        temp_result_se[i] = ' ';
                    }
                }
                strcat(final_content, temp_result_se);
                // strcat(final_content, temp_result_se);
                //  strcpy(result, final_content);
                // printf("%s\n",final_content);
                strcpy(result, final_content);
            }
        }
        else
        {
            num = 0;
            printf("Please input a exist email number\n");
        }
    } while (num == 0);
    return result;
}

void displaybysubjects()
{
    MYAPP_LOGD(TAG, "In displaybysubjects func");
#ifdef release
    // info level
    char *path = "./resource/";
#else
    char *path = "../resource/";
#endif
    DIR *dir;
    char pathname[255];
    if ((dir = opendir(path)) == 0)
    {
        printf("open %s failed!\n", path);
    }
    struct dirent *stdir;
    FILE *fp;
    char *str;
    char txt[1000];
    char *content;
    char *ifFind;
    int filesize;
    int filenum = 0;
    int cor_filenum = 0;
    while (1)
    {
        if ((stdir = readdir(dir)) == 0)
        {
            printf("You have %d emails.\n", filenum);
            break;
        }

        if (stdir->d_type == 8)
        {
#ifdef release
            // info level
            char *path = "./resource/";
#else
            char *path = "../resource/";
#endif

            char *final_Path = malloc(100);
            strcat(final_Path, path);
            strcat(final_Path, stdir->d_name);

            fp = fopen(final_Path, "r");
            fseek(fp, 0, SEEK_END);
            filesize = ftell(fp);

            str = (char *)malloc(filesize);

            str[0] = 0;

            rewind(fp);

            while ((fgets(txt, 1000, fp)) != NULL)
            {
                strcat(str, txt);
            }
            MYAPP_LOGD(TAG, "%s\n", str);
            content = strstr(str, "Subject");
            while (content != NULL)
            {
                MYAPP_LOGD(TAG, "%s\n", content);
                content = strstr(content, " ");
                char *str_end = strstr(content, "\n");
                char final_content[str_end - content];
                strncpy(final_content, content, str_end - content);
                printf("Subject of %s is %s\n", stdir->d_name, final_content);
                content = strstr(str_end, "Subject");
            }
            // fclose(fp);
            filenum = filenum + 1;
        }
    }

    // return result;
}

void download_mail()
{
    MYAPP_LOGD(TAG, "In download_mail func");
    printf("Please input the mail number\n");
    int num = input_email_num();
    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
    memset(recvbuf, 0, sizeof(recvbuf));

    sprintf(sendbuf, "RETR %d\r\n", num);
    tcp_send_data(sendbuf, recvbuf, 3);
    char *result = search_decode_whole(recvbuf, result);
    // char *out = display_subjects();
    printf("Please input the mail name\n");
    char *name = input_email_name();
    int i = save_file(name, result);

    memset(recvbuf, 0, sizeof(recvbuf));
    sprintf(sendbuf, "DELE %d\r\n", num);
    tcp_send_data(sendbuf, recvbuf, 3);
}

void prog_quit()
{
    MYAPP_LOGD(TAG, "In prog_quit func");
}

char *search_decode_content(char *buf, char *ptr)
{
    char *ptr_end = strstr(ptr, "\r\n");
    char content[ptr_end - ptr];
    strncpy(content, ptr, ptr_end - ptr);
    char *content_decode = base64_decode(content);
    MYAPP_LOGD(TAG, "%s", content_decode);
    return content_decode;
}

char *search_decode_whole(char *buf, char *out)
{
    char *ptr = strstr(buf, "\r\n\r\n") + 4;
    char *content_decode = search_decode_content(buf, ptr);
    int len = ptr - buf;
    memset(whole_decode, '\0', ((ptr - buf + strlen(content_decode)) + 4) * sizeof(char));
    strcpy(whole_decode, buf);
    strcat(whole_decode, content_decode);
    MYAPP_LOGD(TAG, "Content:%s", whole_decode);
    return whole_decode;
}

unsigned char *base64_decode(unsigned char *code)
{
    //根据base64表，以字符找到对应的十进制数据
    int table[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0,
                   63, 52, 53, 54, 55, 56, 57, 58,
                   59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0,
                   1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
                   13, 14, 15, 16, 17, 18, 19, 20, 21,
                   22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26,
                   27, 28, 29, 30, 31, 32, 33, 34, 35,
                   36, 37, 38, 39, 40, 41, 42, 43, 44,
                   45, 46, 47, 48, 49, 50, 51};
    long len;
    long str_len;
    unsigned char *res;
    int i, j;

    //计算解码后的字符串长度
    len = strlen(code);
    //判断编码后的字符串后是否有=
    if (strstr(code, "=="))
        str_len = len / 4 * 3 - 2;
    else if (strstr(code, "="))
        str_len = len / 4 * 3 - 1;
    else
        str_len = len / 4 * 3;

    res = malloc(sizeof(unsigned char) * str_len + 1);
    memset(res, '\0', strlen(res));

    //以4个字符为一位进行解码
    for (i = 0, j = 0; i < len - 2; j += 3, i += 4)
    {
        res[j] = ((unsigned char)table[code[i]]) << 2 | (((unsigned char)table[code[i + 1]]) >> 4);           //取出第一个字符对应base64表的十进制数的前6位与第二个字符对应base64表的十进制数的后2位进行组合
        res[j + 1] = (((unsigned char)table[code[i + 1]]) << 4) | (((unsigned char)table[code[i + 2]]) >> 2); //取出第二个字符对应base64表的十进制数的后4位与第三个字符对应bas464表的十进制数的后4位进行组合
        res[j + 2] = (((unsigned char)table[code[i + 2]]) << 6) | ((unsigned char)table[code[i + 3]]);        //取出第三个字符对应base64表的十进制数的后2位与第4个字符进行组合
    }

    return res;
}

int save_file(char *name, char *content)
{
    char whole_name[20];
#ifdef release
    // info level
    sprintf(whole_name, "./resource/%s", name);
#else
    sprintf(whole_name, "../resource/%s", name);
#endif

    FILE *p = NULL;
    p = fopen(whole_name, "w+");
    fprintf(p, "%s", whole_decode);
    fflush(p);

    free(name);
    memset(whole_decode, '\0', strlen(whole_decode));

    return 1;
}

int checkinput(char *buf, int mode)
{
    switch (mode)
    {
    case 1:
        // check if one number
        if (isdigit(buf[0]))
        {
            return 1;
        }
        else
        {
            return 0;
        }
    default:
        return 0;
    }
}
int checkinput_num(int i)
{
    int temp = 0;
    temp = get_list(2);
    if (i <= temp && i > 0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}